home *** CD-ROM | disk | FTP | other *** search
/ io Programmo 60 / IOPROG_60.ISO / soft / c++ / gsl-1.1.1-setup.exe / {app} / src / specfunc / legendre_poly.c < prev    next >
Encoding:
C/C++ Source or Header  |  2002-04-18  |  14.4 KB  |  555 lines

  1. /* specfunc/legendre_poly.c
  2.  * 
  3.  * Copyright (C) 1996, 1997, 1998, 1999, 2000 Gerard Jungman
  4.  * 
  5.  * This program is free software; you can redistribute it and/or modify
  6.  * it under the terms of the GNU General Public License as published by
  7.  * the Free Software Foundation; either version 2 of the License, or (at
  8.  * your option) any later version.
  9.  * 
  10.  * This program is distributed in the hope that it will be useful, but
  11.  * WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  13.  * General Public License for more details.
  14.  * 
  15.  * You should have received a copy of the GNU General Public License
  16.  * along with this program; if not, write to the Free Software
  17.  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  18.  */
  19.  
  20. /* Author:  G. Jungman */
  21.  
  22. #include <config.h>
  23. #include <gsl/gsl_math.h>
  24. #include <gsl/gsl_errno.h>
  25. #include <gsl/gsl_sf_bessel.h>
  26. #include <gsl/gsl_sf_exp.h>
  27. #include <gsl/gsl_sf_gamma.h>
  28. #include <gsl/gsl_sf_log.h>
  29. #include <gsl/gsl_sf_pow_int.h>
  30. #include <gsl/gsl_sf_legendre.h>
  31.  
  32. #include "error.h"
  33.  
  34. /*-*-*-*-*-*-*-*-*-*-*-* Functions with Error Codes *-*-*-*-*-*-*-*-*-*-*-*/
  35.  
  36. int
  37. gsl_sf_legendre_P1_e(double x, gsl_sf_result * result)
  38. {
  39.   /* CHECK_POINTER(result) */
  40.  
  41.   {
  42.     result->val = x;
  43.     result->err = 0.0;
  44.     return GSL_SUCCESS;
  45.   }
  46. }
  47.  
  48. int
  49. gsl_sf_legendre_P2_e(double x, gsl_sf_result * result)
  50. {
  51.   /* CHECK_POINTER(result) */
  52.  
  53.   {
  54.     result->val = 0.5*(3.0*x*x - 1.0);
  55.     result->err = GSL_DBL_EPSILON * (fabs(3.0*x*x) + 1.0);
  56.     return GSL_SUCCESS;
  57.   }
  58. }
  59.  
  60. int
  61. gsl_sf_legendre_P3_e(double x, gsl_sf_result * result)
  62. {
  63.   /* CHECK_POINTER(result) */
  64.  
  65.   {
  66.     result->val = 0.5*x*(5.0*x*x - 3.0);
  67.     result->err = GSL_DBL_EPSILON * (fabs(result->val) + 0.5 * fabs(x) * (fabs(5.0*x*x) + 3.0));
  68.     return GSL_SUCCESS;
  69.   }
  70. }
  71.  
  72.  
  73. int
  74. gsl_sf_legendre_Pl_e(const int l, const double x, gsl_sf_result * result)
  75.   /* CHECK_POINTER(result) */
  76.  
  77.   if(l < 0 || x < -1.0 || x > 1.0) {
  78.     DOMAIN_ERROR(result);
  79.   }
  80.   else if(l == 0) {
  81.     result->val = 1.0;
  82.     result->err = 0.0;
  83.     return GSL_SUCCESS;
  84.   }
  85.   else if(l == 1) {
  86.     result->val = x;
  87.     result->err = 0.0;
  88.     return GSL_SUCCESS;
  89.   }
  90.   else if(l == 2) {
  91.     result->val = 0.5 * (3.0*x*x - 1.0);
  92.     result->err = 3.0 * GSL_DBL_EPSILON * fabs(result->val);
  93.     return GSL_SUCCESS;
  94.   }
  95.   else if(x == 1.0) {
  96.     result->val = 1.0;
  97.     result->err = 0.0;
  98.     return GSL_SUCCESS;
  99.   }
  100.   else if(x == -1.0) {
  101.     result->val = ( GSL_IS_ODD(l) ? -1.0 : 1.0 );
  102.     result->err = 0.0;
  103.     return GSL_SUCCESS;
  104.   }
  105.   else if(l < 100000) {
  106.     /* Compute by upward recurrence on l.
  107.      */
  108.     double p_mm   = 1.0;     /* P_0(x) */
  109.     double p_mmp1 = x;        /* P_1(x) */
  110.     double p_ell = p_mmp1;
  111.     int ell;
  112.  
  113.     for(ell=2; ell <= l; ell++){
  114.       p_ell = (x*(2*ell-1)*p_mmp1 - (ell-1)*p_mm) / ell;
  115.       p_mm = p_mmp1;
  116.       p_mmp1 = p_ell;
  117.     }
  118.  
  119.     result->val = p_ell;
  120.     result->err = (0.5 * ell + 1.0) * GSL_DBL_EPSILON * fabs(p_ell);
  121.     return GSL_SUCCESS;
  122.   }
  123.   else {
  124.     /* Asymptotic expansion.
  125.      * [Olver, p. 473]
  126.      */
  127.     double u  = l + 0.5;
  128.     double th = acos(x);
  129.     gsl_sf_result J0;
  130.     gsl_sf_result Jm1;
  131.     int stat_J0  = gsl_sf_bessel_J0_e(u*th, &J0);
  132.     int stat_Jm1 = gsl_sf_bessel_Jn_e(-1, u*th, &Jm1);
  133.     double pre;
  134.     double B00;
  135.     double c1;
  136.  
  137.     /* B00 = 1/8 (1 - th cot(th) / th^2
  138.      * pre = sqrt(th/sin(th))
  139.      */
  140.     if(th < GSL_ROOT4_DBL_EPSILON) {
  141.       B00 = (1.0 + th*th/15.0)/24.0;
  142.       pre = 1.0 + th*th/12.0;
  143.     }
  144.     else {
  145.       double sin_th = sqrt(1.0 - x*x);
  146.       double cot_th = x / sin_th;
  147.       B00 = 1.0/8.0 * (1.0 - th * cot_th) / (th*th);
  148.       pre = sqrt(th/sin_th);
  149.     }
  150.  
  151.     c1 = th/u * B00;
  152.  
  153.     result->val  = pre * (J0.val + c1 * Jm1.val);
  154.     result->err  = pre * (J0.err + fabs(c1) * Jm1.err);
  155.     result->err += GSL_SQRT_DBL_EPSILON * fabs(result->val);
  156.  
  157.     return GSL_ERROR_SELECT_2(stat_J0, stat_Jm1);
  158.   }
  159. }
  160.  
  161.  
  162. int
  163. gsl_sf_legendre_Pl_array(const int lmax, const double x, double * result_array)
  164. {
  165.   /* CHECK_POINTER(result_array) */
  166.  
  167.   if(lmax < 0 || x < -1.0 || x > 1.0) {
  168.     GSL_ERROR ("domain error", GSL_EDOM);
  169.   }
  170.   else if(lmax == 0) {
  171.     result_array[0] = 1.0;
  172.     return GSL_SUCCESS;
  173.   }
  174.   else if(lmax == 1) {
  175.     result_array[0] = 1.0;
  176.     result_array[1] = x;
  177.     return GSL_SUCCESS;
  178.   }
  179.   else {
  180.     double p_mm   = 1.0;    /* P_0(x) */
  181.     double p_mmp1 = x;        /* P_1(x) */
  182.     double p_ell = p_mmp1;
  183.     int ell;
  184.  
  185.     result_array[0] = 1.0;
  186.     result_array[1] = x;
  187.  
  188.     for(ell=2; ell <= lmax; ell++){
  189.       p_ell = (x*(2*ell-1)*p_mmp1 - (ell-1)*p_mm) / ell;
  190.       p_mm = p_mmp1;
  191.       p_mmp1 = p_ell;
  192.       result_array[ell] = p_ell;
  193.     }
  194.  
  195.     return GSL_SUCCESS;
  196.   }
  197. }
  198.  
  199.  
  200. int
  201. gsl_sf_legendre_Plm_e(const int l, const int m, const double x, gsl_sf_result * result)
  202. {
  203.   /* If l is large and m is large, then we have to worry
  204.    * about overflow. Calculate an approximate exponent which
  205.    * measures the normalization of this thing.
  206.    */
  207.   double dif = l-m;
  208.   double sum = l+m;
  209.   double exp_check = 0.5 * log(2.0*l+1.0) 
  210.                    + 0.5 * dif * (log(dif)-1.0)
  211.                    - 0.5 * sum * (log(sum)-1.0);
  212.  
  213.   /* CHECK_POINTER(result) */
  214.  
  215.   if(m < 0 || l < m || x < -1.0 || x > 1.0) {
  216.     DOMAIN_ERROR(result);
  217.   }
  218.   else if(exp_check < GSL_LOG_DBL_MIN + 10.0){
  219.     /* Bail out. */
  220.     OVERFLOW_ERROR(result);
  221.   }
  222.   else {
  223.     /* Account for the error due to the
  224.      * representation of 1-x.
  225.      */
  226.     const double err_amp = 1.0 / (GSL_DBL_EPSILON + fabs(1.0-fabs(x)));
  227.  
  228.     double p_mm;     /* P_m^m(x) */
  229.     double p_mmp1;   /* P_{m+1}^m(x) */
  230.  
  231.     /* Calculate P_m^m from the analytic result:
  232.      *          P_m^m(x) = (-1)^m (2m-1)!! (1-x^2)^(m/2) , m > 0
  233.      */
  234.     p_mm = 1.0;
  235.     if(m > 0){
  236.       double root_factor = sqrt(1.0-x)*sqrt(1.0+x);
  237.       double fact_coeff = 1.0;
  238.       int i;
  239.       for(i=1; i<=m; i++) {
  240.         p_mm *= -fact_coeff * root_factor;
  241.         fact_coeff += 2.0;
  242.       }
  243.     }
  244.  
  245.     /* Calculate P_{m+1}^m. */
  246.     p_mmp1 = x * (2*m + 1) * p_mm;
  247.  
  248.     if(l == m){
  249.       result->val = p_mm;
  250.       result->err = err_amp * 2.0 * GSL_DBL_EPSILON * fabs(p_mm);
  251.       return GSL_SUCCESS;
  252.     }
  253.     else if(l == m + 1) {
  254.       result->val = p_mmp1;
  255.       result->err = err_amp * 2.0 * GSL_DBL_EPSILON * fabs(p_mmp1);
  256.       return GSL_SUCCESS;
  257.     }
  258.     else{
  259.       double p_ell = 0.0;
  260.       int ell;
  261.     
  262.       /* Compute P_l^m, l > m+1 by upward recurrence on l. */
  263.       for(ell=m+2; ell <= l; ell++){
  264.         p_ell = (x*(2*ell-1)*p_mmp1 - (ell+m-1)*p_mm) / (ell-m);
  265.         p_mm = p_mmp1;
  266.         p_mmp1 = p_ell;
  267.       }
  268.  
  269.       result->val = p_ell;
  270.       result->err = err_amp * (0.5*(l-m) + 1.0) * GSL_DBL_EPSILON * fabs(p_ell);
  271.  
  272.       return GSL_SUCCESS;
  273.     }
  274.   }
  275. }
  276.  
  277.  
  278. int
  279. gsl_sf_legendre_Plm_array(const int lmax, const int m, const double x, double * result_array)
  280. {
  281.   /* If l is large and m is large, then we have to worry
  282.    * about overflow. Calculate an approximate exponent which
  283.    * measures the normalization of this thing.
  284.    */
  285.   double dif = lmax-m;
  286.   double sum = lmax+m;
  287.   double exp_check = 0.5 * log(2.0*lmax+1.0) 
  288.                      + 0.5 * dif * (log(dif)-1.0)
  289.                      - 0.5 * sum * (log(sum)-1.0);
  290.  
  291.   /* CHECK_POINTER(result_array) */
  292.  
  293.   if(m < 0 || lmax < m || x < -1.0 || x > 1.0) {
  294.     GSL_ERROR ("error", GSL_EDOM);
  295.   }
  296.   else if(m > 0 && (x == 1.0 || x == -1.0)) {
  297.     int ell;
  298.     for(ell=m; ell<=lmax; ell++) result_array[ell-m] = 0.0;
  299.     return GSL_SUCCESS;
  300.   }
  301.   else if(exp_check < GSL_LOG_DBL_MIN + 10.0){
  302.     /* Bail out.
  303.      */
  304.     GSL_ERROR ("error", GSL_EOVRFLW);
  305.   }
  306.   else {
  307.     double p_mm;                 /* P_m^m(x)     */
  308.     double p_mmp1;               /* P_{m+1}^m(x) */
  309.  
  310.     /* Calculate P_m^m from the analytic result:
  311.      *          P_m^m(x) = (-1)^m (2m-1)!! (1-x^2)^(m/2) , m > 0
  312.      */
  313.     p_mm = 1.0;
  314.     if(m > 0){
  315.       double root_factor = sqrt(1.0-x)*sqrt(1.0+x);
  316.       double fact_coeff = 1.0;
  317.       int i;
  318.       for(i=1; i<=m; i++){
  319.         p_mm *= -fact_coeff * root_factor;
  320.         fact_coeff += 2.0;
  321.       }
  322.     }
  323.  
  324.     /* Calculate P_{m+1}^m. */
  325.     p_mmp1 = x * (2*m + 1) * p_mm;
  326.  
  327.     if(lmax == m){
  328.       result_array[0] = p_mm;
  329.       return GSL_SUCCESS;
  330.     }
  331.     else if(lmax == m + 1) {
  332.       result_array[0] = p_mm;
  333.       result_array[1] = p_mmp1;
  334.       return GSL_SUCCESS;
  335.     }
  336.     else{
  337.       double p_ell;
  338.       int ell;
  339.  
  340.       result_array[0] = p_mm;
  341.       result_array[1] = p_mmp1;
  342.  
  343.       /* Compute P_l^m, l >= m+2, by upward recursion on l. */
  344.       for(ell=m+2; ell <= lmax; ell++){
  345.         p_ell = (x*(2*ell-1)*p_mmp1 - (ell+m-1)*p_mm) / (ell-m);
  346.         p_mm = p_mmp1;
  347.         p_mmp1 = p_ell;
  348.         result_array[ell-m] = p_ell;
  349.       }
  350.  
  351.       return GSL_SUCCESS;
  352.     }
  353.   }
  354. }
  355.  
  356.  
  357. int
  358. gsl_sf_legendre_sphPlm_e(const int l, int m, const double x, gsl_sf_result * result)
  359. {
  360.   /* CHECK_POINTER(result) */
  361.  
  362.   if(m < 0 || l < m || x < -1.0 || x > 1.0) {
  363.     DOMAIN_ERROR(result);
  364.   }
  365.   else if(m == 0) {
  366.     gsl_sf_result P;
  367.     int stat_P = gsl_sf_legendre_Pl_e(l, x, &P);
  368.     double pre = sqrt((2.0*l + 1.0)/(4.0*M_PI));
  369.     result->val  = pre * P.val;
  370.     result->err  = pre * P.err;
  371.     result->err += 2.0 * GSL_DBL_EPSILON * fabs(result->val);
  372.     return stat_P;
  373.   }
  374.   else if(x == 1.0 || x == -1.0) {
  375.     /* m > 0 here */
  376.     result->val = 0.0;
  377.     result->err = 0.0;
  378.     return GSL_SUCCESS;
  379.   }
  380.   else {
  381.     /* m > 0 and |x| < 1 here */
  382.  
  383.     /* Starting value for recursion.
  384.      * Y_m^m(x) = sqrt( (2m+1)/(4pi m) gamma(m+1/2)/gamma(m) ) (-1)^m (1-x^2)^(m/2) / pi^(1/4)
  385.      */
  386.     gsl_sf_result lncirc;
  387.     gsl_sf_result lnpoch;
  388.     double lnpre_val;
  389.     double lnpre_err;
  390.     gsl_sf_result ex_pre;
  391.     double sr;
  392.     const double sgn = ( GSL_IS_ODD(m) ? -1.0 : 1.0);
  393.     const double y_mmp1_factor = x * sqrt(2.0*m + 3.0);
  394.     double y_mm, y_mm_err;
  395.     double y_mmp1;
  396.     gsl_sf_log_1plusx_e(-x*x, &lncirc);
  397.     gsl_sf_lnpoch_e(m, 0.5, &lnpoch);  /* Gamma(m+1/2)/Gamma(m) */
  398.     lnpre_val = -0.25*M_LNPI + 0.5 * (lnpoch.val + m*lncirc.val);
  399.     lnpre_err = 0.25*M_LNPI*GSL_DBL_EPSILON + 0.5 * (lnpoch.err + fabs(m)*lncirc.err);
  400.     gsl_sf_exp_err_e(lnpre_val, lnpre_err, &ex_pre);
  401.     sr    = sqrt((2.0+1.0/m)/(4.0*M_PI));
  402.     y_mm   = sgn * sr * ex_pre.val;
  403.     y_mmp1 = y_mmp1_factor * y_mm;
  404.     y_mm_err  = 2.0 * GSL_DBL_EPSILON * fabs(y_mm) + sr * ex_pre.err;
  405.     y_mm_err *= 1.0 + 1.0/(GSL_DBL_EPSILON + fabs(1.0-x));
  406.  
  407.     if(l == m){
  408.       result->val  = y_mm;
  409.       result->err  = y_mm_err;
  410.       result->err += 2.0 * GSL_DBL_EPSILON * fabs(y_mm);
  411.       return GSL_SUCCESS;
  412.     }
  413.     else if(l == m + 1) {
  414.       result->val  = y_mmp1;
  415.       result->err  = fabs(y_mmp1_factor) * y_mm_err;
  416.       result->err += 2.0 * GSL_DBL_EPSILON * fabs(y_mmp1);
  417.       return GSL_SUCCESS;
  418.     }
  419.     else{
  420.       double y_ell = 0.0;
  421.       int ell;
  422.  
  423.       /* Compute Y_l^m, l > m+1, upward recursion on l. */
  424.       for(ell=m+2; ell <= l; ell++){
  425.         const double rat1 = (double)(ell-m)/(double)(ell+m);
  426.     const double rat2 = (ell-m-1.0)/(ell+m-1.0);
  427.         const double factor1 = sqrt(rat1*(2*ell+1)*(2*ell-1));
  428.         const double factor2 = sqrt(rat1*rat2*(2*ell+1)/(2*ell-3));
  429.         y_ell = (x*y_mmp1*factor1 - (ell+m-1)*y_mm*factor2) / (ell-m);
  430.         y_mm   = y_mmp1;
  431.         y_mmp1 = y_ell;
  432.       }
  433.  
  434.       result->val  = y_ell;
  435.       result->err  = (0.5*(l-m) + 1.0) * GSL_DBL_EPSILON * fabs(y_ell);
  436.       result->err += fabs(y_mm_err/y_mm) * fabs(y_ell);
  437.  
  438.       return GSL_SUCCESS;
  439.     }
  440.   }
  441. }
  442.  
  443.  
  444. int
  445. gsl_sf_legendre_sphPlm_array(const int lmax, int m, const double x, double * result_array)
  446. {
  447.   /* CHECK_POINTER(result_array) */
  448.  
  449.   if(m < 0 || lmax < m || x < -1.0 || x > 1.0) {
  450.     GSL_ERROR ("error", GSL_EDOM);
  451.   }
  452.   else if(m > 0 && (x == 1.0 || x == -1.0)) {
  453.     int ell;
  454.     for(ell=m; ell<=lmax; ell++) result_array[ell-m] = 0.0;
  455.     return GSL_SUCCESS;
  456.   }
  457.   else {
  458.     double y_mm;
  459.     double y_mmp1;
  460.  
  461.     if(m == 0) {
  462.       y_mm   = 0.5/M_SQRTPI;          /* Y00 = 1/sqrt(4pi) */
  463.       y_mmp1 = x * M_SQRT3 * y_mm;
  464.     }
  465.     else {
  466.       /* |x| < 1 here */
  467.  
  468.       gsl_sf_result lncirc;
  469.       gsl_sf_result lnpoch;
  470.       double lnpre;
  471.       const double sgn = ( GSL_IS_ODD(m) ? -1.0 : 1.0);
  472.       gsl_sf_log_1plusx_e(-x*x, &lncirc);
  473.       gsl_sf_lnpoch_e(m, 0.5, &lnpoch);  /* Gamma(m+1/2)/Gamma(m) */
  474.       lnpre = -0.25*M_LNPI + 0.5 * (lnpoch.val + m*lncirc.val);
  475.       y_mm   = sqrt((2.0+1.0/m)/(4.0*M_PI)) * sgn * exp(lnpre);
  476.       y_mmp1 = x * sqrt(2.0*m + 3.0) * y_mm;
  477.     }
  478.  
  479.     if(lmax == m){
  480.       result_array[0] = y_mm;
  481.       return GSL_SUCCESS;
  482.     }
  483.     else if(lmax == m + 1) {
  484.       result_array[0] = y_mm;
  485.       result_array[1] = y_mmp1;
  486.       return GSL_SUCCESS;
  487.     }
  488.     else{
  489.       double y_ell;
  490.       int ell;
  491.  
  492.       result_array[0] = y_mm;
  493.       result_array[1] = y_mmp1;
  494.  
  495.       /* Compute Y_l^m, l > m+1, upward recursion on l. */
  496.       for(ell=m+2; ell <= lmax; ell++){
  497.         const double rat1 = (double)(ell-m)/(double)(ell+m);
  498.     const double rat2 = (ell-m-1.0)/(ell+m-1.0);
  499.         const double factor1 = sqrt(rat1*(2*ell+1)*(2*ell-1));
  500.         const double factor2 = sqrt(rat1*rat2*(2*ell+1)/(2*ell-3));
  501.         y_ell = (x*y_mmp1*factor1 - (ell+m-1)*y_mm*factor2) / (ell-m);
  502.         y_mm   = y_mmp1;
  503.         y_mmp1 = y_ell;
  504.     result_array[ell-m] = y_ell;
  505.       }
  506.     }
  507.  
  508.     return GSL_SUCCESS;
  509.   }
  510. }
  511.  
  512. #ifndef HIDE_INLINE_STATIC
  513. int
  514. gsl_sf_legendre_array_size(const int lmax, const int m)
  515. {
  516.   return lmax-m+1;
  517. }
  518. #endif
  519.  
  520. /*-*-*-*-*-*-*-*-*-* Functions w/ Natural Prototypes *-*-*-*-*-*-*-*-*-*-*/
  521.  
  522. #include "eval.h"
  523.  
  524. double gsl_sf_legendre_P1(const double x)
  525. {
  526.   EVAL_RESULT(gsl_sf_legendre_P1_e(x, &result));
  527. }
  528.  
  529. double gsl_sf_legendre_P2(const double x)
  530. {
  531.   EVAL_RESULT(gsl_sf_legendre_P2_e(x, &result));
  532. }
  533.  
  534. double gsl_sf_legendre_P3(const double x)
  535. {
  536.   EVAL_RESULT(gsl_sf_legendre_P3_e(x, &result));
  537. }
  538.  
  539. double gsl_sf_legendre_Pl(const int l, const double x)
  540. {
  541.   EVAL_RESULT(gsl_sf_legendre_Pl_e(l, x, &result));
  542. }
  543.  
  544. double gsl_sf_legendre_Plm(const int l, const int m, const double x)
  545. {
  546.   EVAL_RESULT(gsl_sf_legendre_Plm_e(l, m, x, &result));
  547. }
  548.  
  549. double gsl_sf_legendre_sphPlm(const int l, const int m, const double x)
  550. {
  551.   EVAL_RESULT(gsl_sf_legendre_sphPlm_e(l, m, x, &result));
  552. }
  553.  
  554.